# -*- makefile -*-
# vi:se ft=make:

###############################################################################

include $(srcdir)/Modules.generic

SUBSYSTEMS += LIBUART

PREPROCESS_PARTS 	+= $(CONFIG_ABI) $(CONFIG_XARCH) libuart

ifeq ($(CONFIG_BIT64),y)
PREPROCESS_PARTS += 64bit arm_esr_traps
BITS := 64
else
PREPROCESS_PARTS += 32bit recover_jmpbuf
PREPROCESS_PARTS-$(CONFIG_MMU) += abs_syscalls
BITS := 32
endif

# On ARMv7 and above Fiasco uses broadcast TLB invalidation instructions. On
# MPU systems, IPIs are always required because each CPU has its own MPU
# instance.
NEED_TLB_IPI := $(if $(CONFIG_MMU),$(if $(CONFIG_ARM_V7PLUS),,y),y)
PREPROCESS_PARTS-$(CONFIG_MP)                 += $(if $(NEED_TLB_IPI),need_xcpu_tlb_flush)
PREPROCESS_PARTS-$(CONFIG_JDB)                += debug log
PREPROCESS_PARTS-$(CONFIG_ARM_CACHE_L2CXX0)   += outer_cache outer_cache_l2cxx0

PREPROCESS_PARTS-$(CONFIG_ARM_920T)                 += arm_v5 vcache
PREPROCESS_PARTS-$(CONFIG_ARM_926)                  += arm_v5 vcache
PREPROCESS_PARTS-$(CONFIG_CPU_VIRT)                 += vgic arm_esr_traps
PREPROCESS_PARTS-$(CONFIG_ARM_PT48)                 += arm_pt_48
PREPROCESS_PARTS-$(CONFIG_ARM_SVE)                  += fpu_alloc_typed

PREPROCESS_PARTS-$(CONFIG_IOMMU)                    += virtual_space_iface


#
# TYPES subsystem
#

PRIVATE_INCDIR += types/$(CONFIG_XARCH)/$(BITS) types/$(CONFIG_XARCH) types

VPATH_LIBUART  := $(srcdir)/lib/uart
PRIVATE_INCDIR += lib/uart

#
# DRIVERS Subsystem
#
DRIVERS 		:= libdrivers.a libgluedriverslibc.a
VPATH			+= drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
PRIVATE_INCDIR		+= drivers/$(CONFIG_XARCH)/$(BITS) drivers/$(CONFIG_XARCH) drivers
INTERFACES_DRIVERS 	:= sa1100 mux_console console uart filter_console \
			   h3xxx io mem mmu reset processor delayloop ve_sysregs
INTERFACES_DRIVERS	+= $(if $(CONFIG_UART_CHECKSUM),stream_crc32)
INTERFACES_DRIVERS      += fb_console
io_IMPL			:= io io-arm
mmu_IMPL		:= mmu mmu-arm mmu-arm-$(BITS)
mem_IMPL		:= mem mem-arm
uart_IMPL		:= uart uart-libuart
reset_IMPL		:=
processor_IMPL		:= processor processor-arm-$(BITS) processor-arm
CXXSRC_DRIVERS		:= glue_libc.cc
NOOPT			+= $(patsubst %.o, %, $(OBJ_DRIVERS))
ALWAYS_INLINE           += mem

#
# LIBREGEX subsystem (only for Jdb)
#
LIBREGEX	:= libregex.a
VPATH		+= lib/regex
PRIVATE_INCDIR	+= lib/regex
CSRC_LIBREGEX	:= rx.c
NOOPT		+= $(patsubst %.o, %, $(OBJ_LIBREGEX))

#
# LIBC Subsystem addendum
#
CSRC_LIBC       += aeabi.c atexit-aeabi.c


#
# LIBGZIP subsystem (only for Jdb)
#
ifneq ($(CONFIG_JDB_GZIP),)
  LIBGZIP		:= libgzip.a
  VPATH			+= lib/gzip
  PRIVATE_INCDIR	+= lib/gzip
  CSRC_LIBGZIP		:= adler32.c crc32.c gzip.c trees.c deflate.c zutil.c
  NOOPT			+= $(patsubst %.o, %, $(OBJ_LIBGZIP))
  $(foreach f, adler32 crc32 deflate trees zutil, \
    $(eval CFLAGS_$(f) += $(WNO_DEPRECATED_NON_PROTOTYPE) \
      -Wno-old-style-definition -Wno-strict-prototypes))
endif


#
# JABI Subsystem
#
JABI			:= libjabi.a
VPATH			+= jabi/$(CONFIG_XARCH)/$(BITS) jabi/$(CONFIG_XARCH) jabi
INTERFACES_JABI		:= jdb_ktrace jdb_obj_info

#
# FONTS subsystem
#
SUBSYSTEMS              += FONTS
FONTS                   := libfonts.a
FONT_FILES              := vgafont.psf
VPATH                   += ../data/fonts
OBJ_FONTS               := $(addsuffix .bin.o,$(FONT_FILES))
NOOPT                   += $(patsubst %.o, %, $(OBJ_FONTS))
KERNEL_EXTRA_LIBS       += $(FONTS)

#
# KERNEL subsystem
#
KERNEL 		:= fiasco
KERNEL_EXTRA 	:= Symbols kernel.arm.lds fiasco.debug
VPATH 		+= kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern
VPATH		+= jdb/arm/$(BITS) jdb/arm jdb
PRIVATE_INCDIR 	+= kern/$(CONFIG_XARCH)/$(BITS) kern/$(CONFIG_XARCH) kern

INTERFACES_KERNEL += 	__main kmem_space boot_uart_init     \
			irq_chip_generic bootstrap                  \
			outer_cache utcb_support                    \
			smc_call psci alternatives

NEED_MEM_CHUNK = $(or $(and $(CONFIG_ARM_GIC_MSI),$(CONFIG_HAVE_ARM_GICV3)),\
                      $(CONFIG_IOMMU))

INTERFACES_KERNEL-$(CONFIG_MPU) += mpu kmem_mpu
INTERFACES_KERNEL-$(NEED_MEM_CHUNK) += mem_chunk
INTERFACES_KERNEL-$(CONFIG_ARM_ACPI) += acpi acpi_fadt
INTERFACES_KERNEL-$(CONFIG_ARM_MPCORE) += scu
INTERFACES_KERNEL-$(CONFIG_ARM_CORTEX_A9) += scu
INTERFACES_KERNEL-$(CONFIG_BIT32)-$(CONFIG_MMU) += kern_lib_page
INTERFACES_KERNEL-$(CONFIG_BIT32) += mem_op
INTERFACES_KERNEL-$(CONFIG_SERIAL) += uart_console
INTERFACES_KERNEL-$(CONFIG_ARM_EM_TZ) += vm
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT) += hyp_vm_state vgic vgic_global
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT)-$(CONFIG_HAVE_ARM_GICV2) += vgic_v2
INTERFACES_KERNEL-$(CONFIG_CPU_VIRT)-$(CONFIG_HAVE_ARM_GICV3) += vgic_v3
INTERFACES_KERNEL-$(CONFIG_ARM_SMC_USER) += smc_user
INTERFACES_KERNEL-$(CONFIG_ARM_GIC) += gic_dist gic
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV3) += gic_redist
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV2) += gic_v2 gic_cpu_v2
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GICV3) += gic_v3 gic_cpu_v3 gic_its
INTERFACES_KERNEL-$(CONFIG_HAVE_ARM_GIC_MSI) += irq_mgr_msi
INTERFACES_KERNEL-$(CONFIG_ARM_GIC_MSI)-$(CONFIG_HAVE_ARM_GICV3) += gic_mem gic_msi

INTERFACES_KERNEL-$(CONFIG_IOMMU) += iommu arm_dmar dmar_space
INTERFACES_KERNEL += boot_infos

acpi_IMPL               := acpi acpi-arm
alternatives_IMPL	:= alternatives alternatives-arm
bootstrap_IMPL		:= bootstrap bootstrap-arm-$(BITS)
clock_IMPL              := clock
config_IMPL	  	:= config config-arm
context_base_IMPL       := context_base context_base-arm
context_IMPL	  	:= context context-arm context-arm-$(BITS) \
                           context-vcpu context-arm-hyp context-arm-hyp-$(BITS)
continuation_IMPL	:= continuation-arm
cpu_IMPL	  	:= cpu cpu-arm cpu-arm-$(BITS)
cpu_lock_IMPL  	  	:= cpu_lock cpu_lock-generic
dmar_space_IMPL		:= dmar_space \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_400),dmar_space-smmuv2) \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_500),dmar_space-smmuv2) \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_V3),dmar_space-smmuv3)
ifeq ($(CONFIG_BIT64),y)
  entry_frame_IMPL	:= entry_frame-arm
else
  entry_frame_IMPL	:= entry_frame entry_frame-arm
endif
fpu_IMPL		:= fpu fpu-arm
ifeq ($(CONFIG_ARM_SVE),y)
fpu_alloc_IMPL		:= fpu_alloc fpu_alloc-arm
endif
gic_IMPL		:= gic
gic_cpu_v3_IMPL		:= gic_cpu_v3 gic_cpu_v3-$(BITS)
gic_dist_IMPL		:= gic_dist
globals_IMPL		:= globals globals-arm
hyp_vm_state_IMPL	:= hyp_vm_state hyp_vm_state-$(BITS)
iommu_IMPL		:= iommu-arm \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_400),iommu-arm-smmuv2) \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_500),iommu-arm-smmuv2) \
                           $(if $(CONFIG_IOMMU_ARM_SMMU_V3),iommu-arm-smmuv3)
ipi_IMPL		:= ipi ipi-arm
kdb_ke_IMPL		+= kdb_ke-arm
kernel_task_IMPL	:= kernel_task kernel_task-arm
kernel_thread_IMPL	:= kernel_thread kernel_thread-arm \
			   kernel_thread-arm-$(BITS)
kernel_uart_IMPL  	:= kernel_uart kernel_uart-libuart
map_util_IMPL		:= map_util map_util-mem map_util-objs
mem_layout_IMPL		:= mem_layout mem_layout-arm-$(BITS) \
			   mem_layout-arm
mem_space_IMPL		:= mem_space mem_space-arm mem_space-arm-$(BITS)
mem_unit_IMPL		:= mem_unit mem_unit-arm-$(BITS)
kmem_IMPL		:= kmem kmem-arm
kmem_alloc_IMPL		:= kmem_alloc kmem_alloc-arm
kmem_mmio_IMPL		:= kmem_mmio kmem_mmio-arm
kmem_space_IMPL		:= kmem_space kmem_space-arm-$(BITS)
outer_cache_IMPL	:= outer_cache outer_cache-l2cxx0
page_IMPL		:= page page-arm page-arm-$(BITS)
paging_IMPL	  	:= paging paging-arm paging-arm-$(BITS)
perf_cnt_IMPL		:= perf_cnt perf_cnt-arm perf_cnt-arm-$(BITS)
pic_IMPL		:= pic
platform_control_IMPL   += platform_control-arm platform_control-arm-psci
platform_control_object_IMPL := platform_control_object \
                                platform_control_object-arm
psci_IMPL		:= psci-arm
sched_context_IMPL	:= sched_context-wfq sched_context-fixed_prio \
			   sched_context-fp_wfq sched_context
scu_IMPL                := scu
space_IMPL		:= space space-arm
spin_lock_IMPL		:= spin_lock spin_lock-arm spin_lock-arm-$(BITS)
startup_IMPL		:= startup startup-arm
sys_call_page_IMPL	:= sys_call_page \
			   $(if $(and $(CONFIG_BIT32),$(CONFIG_MMU)), sys_call_page-arm)
task_IMPL		:= task task-arm
thread_IMPL	  	:= thread thread-arm thread-arm-hyp \
			   thread-jdb thread-jdb-$(BITS) thread-ipc \
			   thread-pagefault  thread-log \
			   thread-vcpu thread-arm-$(BITS)
timer_IMPL		:= timer timer-arm
timer_tick_IMPL		:= timer_tick timer_tick-arm
utcb_init_IMPL		:= utcb_init utcb_init-arm
utcb_support_IMPL       := utcb_support utcb_support-arm
vgic_IMPL		:= vgic
vgic_v3_IMPL		:= vgic_v3 vgic_v3-$(BITS)
vmem_alloc_IMPL	  	:= vmem_alloc vmem_alloc-arch
tb_entry_IMPL		:= tb_entry tb_entry-arm
mpu_IMPL                := mpu mpu-arm-$(BITS)
global_data_IMPL        := global_data global_data-arm-$(BITS)
vcpu_IMPL		:= vcpu vcpu-arm


ifeq ("$(CONFIG_JDB)","y")
JDB			:= jdb_compound.o
SUBSYSTEMS		+= JDB
INTERFACES_JDB		+= jdb_trace_set jdb_log jdb_console_buffer

INTERFACES_JDB-$(CONFIG_PERF_CNT) += jdb_perf
INTERFACES_JDB-$(CONFIG_MMU) += jdb_ptab

CXXSRC_JDB := tb_entry_output.cc


jdb_IMPL		+= jdb-arm
jdb_kern_info_IMPL	:= jdb_kern_info jdb_kern_info-arm \
			   jdb_kern_info-bench jdb_kern_info-bench-arm \
			   jdb_kern_info-cpu-arm
jdb_dump_entry_frame_IMPL:= jdb_dump_entry_frame-arm
jdb_tcb_IMPL		+= jdb_tcb-arm
jdb_ptab_IMPL		:= jdb_ptab jdb_ptab-arm
jdb_entry_frame_IMPL	:= jdb_entry_frame-arm
jdb_trace_set_IMPL	:= jdb_trace_set jdb_trace_set-arm \
			   jdb_trace_set-arm-$(BITS)
jdb_bp_IMPL		:= jdb_bp-arm
thread_IMPL		+= thread-debug
jdb_tbuf_fe_IMPL        := jdb_tbuf_fe jdb_tbuf_fe-arm

endif

CXXSRC_KERNEL		:= kernel_panic.cc libc_backend_lock.cc
ASSRC_KERNEL	  	:= $(if $(CONFIG_MP),tramp-mp.S)
ASSRC_KERNEL            += $(if $(CONFIG_BIT32),$(if $(CONFIG_CPU_VIRT),hvt.S,ivt.S),ivt.S)
ASSRC_KERNEL            += kip-time.S
CPPFLAGS                += $(if $(MPCORE_PHYS_BASE),-DMPCORE_PHYS_BASE=$(MPCORE_PHYS_BASE))
CPPFLAGS                += -DRAM_PHYS_BASE=$(RAM_PHYS_BASE)

NOOPT			+= $(filter jdb%,\
			     $(foreach in,$(INTERFACES_KERNEL), \
			       $(if $($(in)_IMPL),$($(in)_IMPL),$(in))))
NOOPT			+= tb_entry tb_entry_output


#
# CRT0 subsystem
#
CRT0 		:= crt0.o
ASSRC_CRT0	:= crt0.S


#
# CXXLIB Subsystem
#
CXXLIB 			:= libcxx.a
VPATH			+= lib/cxxlib
CXXSRC_CXXLIB	 	:= paranoia.cc

#
# LIBK subsystem
#
LIBK 		:= libk.a
VPATH          	+= lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk
PRIVATE_INCDIR 	+= lib/libk/$(CONFIG_XARCH)/$(BITS) lib/libk/$(CONFIG_XARCH) lib/libk

ifneq ($(CONFIG_COV),)
 SUBSYSTEMS  += LIBCOV
 KERNEL_EXTRA_LIBS += $(LIBCOV)
 PRIVATE_INCDIR += lib/gcov/include
 INTERFACES_KERNEL-$(CONFIG_JDB) += jdb_cov_module
endif

#INTERFACES_LIBK:= atomic lock_guard profile uuencode gmon unistd panic
INTERFACES_LIBK := std_macros atomic lock_guard scaler_shift
ifeq ($(CONFIG_BIT32),y)
CSRC_LIBK       += gcc_lib.c
ASSRC_LIBK      += gcc_lib-aeabi.S
endif
CXXSRC_LIBK     += construction.cc
atomic_IMPL     := atomic atomic-arm-$(BITS) atomic-arm
scaler_shift_IMPL := scaler_shift scaler_shift-arm

#
# SIMPLEMALLOC
#
SIMPLEMALLOC     := libsimple_malloc.a
VPATH             += lib/simple_malloc
PRIVATE_INCDIR    += lib/simple_malloc
CXXSRC_SIMPLEMALLOC = simple_malloc.cc

ifeq ("$(CONFIG_JDB_DISASM)","y")
  # $(srcdir)/lib/disasm may be removed
  ifeq ($(wildcard $(srcdir)/lib/disasm),)
    $(error $(srcdir)/lib/disasm is missing, disable CONFIG_JDB_DISASM)
  endif
  SUBSYSTEMS          += LIBDISASM
  KERNEL_EXTRA_LIBS   += $(LIBDISASM)
  PREPROCESS_PARTS    += jdb_disasm

  LIBDISASM           := libdisasm.a
  VPATH               += lib/disasm lib/disasm/capstone
  PRIVATE_INCDIR      += lib/disasm lib/disasm/capstone/include
  CXXSRC_LIBDISASM    := disasm.cc
  CSRC_LIBDISASM      := cs.c utils.c \
                         MCInst.c MCInstrDesc.c MCRegisterInfo.c SStream.c
  ifeq ("$(CONFIG_BIT32)","y")
    VPATH             += lib/disasm/capstone/arch/ARM
    CSRC_LIBDISASM    += ARMModule.c ARMInstPrinter.c \
			 ARMDisassembler.c ARMMapping.c
    CPPFLAGS          += -DCAPSTONE_HAS_ARM
    CFLAGS_ARMDisassembler = -Wno-unused-parameter
    CFLAGS_ARMMapping      = -Wno-unused-parameter
    CFLAGS_ARMInstPrinter  = -Wno-bad-function-cast -Wno-unused-parameter
    $(foreach f, $(patsubst %.c, %, $(CSRC_LIBDISASM)), \
      $(eval CFLAGS_$(f) += -mno-unaligned-access))
  else
    VPATH             += lib/disasm/capstone/arch/AArch64
    CSRC_LIBDISASM    += AArch64Module.c AArch64InstPrinter.c \
			 AArch64Disassembler.c AArch64Mapping.c \
			 AArch64BaseInfo.c
    CPPFLAGS          += -DCAPSTONE_HAS_ARM64
    CFLAGS_AArch64Mapping       = -Wno-unused-parameter
    CFLAGS_AArch64Disassembler  = -Wno-unused-parameter
    CFLAGS_AArch64InstPrinter   = -Wno-bad-function-cast -Wno-unused-parameter
    # Clang does not support fallthrough warning elision via comments
    CFLAGS_AArch64Mapping      += $(if $(CC_IS_CLANG),-Wno-implicit-fallthrough)
    CFLAGS_AArch64Disassembler += $(if $(CC_IS_CLANG),-Wno-implicit-fallthrough)
  endif
endif

ifeq ("$(CONFIG_JDB)","y")

ifneq ($(CONFIG_JDB_GZIP),)
 ifneq ($(wildcard $(srcdir)/lib/gzip),)
  SUBSYSTEMS		+= LIBGZIP
  KERNEL_EXTRA_LIBS	+= $(LIBGZIP)
  INTERFACES_KERNEL	+= jdb_gzip
 endif
endif

ifneq ($(wildcard $(srcdir)/lib/regex),)
  SUBSYSTEMS            += LIBREGEX
  KERNEL_EXTRA_LIBS     += $(LIBREGEX)
  PREPROCESS_PARTS      += jdb_regex
endif

ifneq ($(filter LIBREGEX LIBDISASM,$(SUBSYSTEMS)),)
  SUBSYSTEMS          += SIMPLEMALLOC
  KERNEL_EXTRA_LIBS   += $(SIMPLEMALLOC)
endif

endif

#
# VERSION subsystem
#
VERSION		:= version.h

TCBOFFSET	:= tcboffset.h
CXXSRC_TCBOFFSET	:= tcboffset.cc dump_tcboffsets.cc

BSP_NAME         := $(patsubst "%",%,$(CONFIG_BSP_NAME))
BSP_SRC_DIR      := kern/arm/bsp/$(BSP_NAME)
MODULES_FILE_BSP := $(srcdir)/$(BSP_SRC_DIR)/Modules
ifeq ($(wildcard $(MODULES_FILE_BSP)),)
  $(error No BSP name defined or no BSP Modules file available)
endif

include $(MODULES_FILE_BSP)
VPATH                   += $(BSP_SRC_DIR)
PREPROCESS_PARTS	+= $(PREPROCESS_PARTS-y)
INTERFACES_KERNEL       += $(INTERFACES_KERNEL-y) $(INTERFACES_KERNEL-y-y)
INTERFACES_JDB		+= $(INTERFACES_JDB-y)
TRAMP_MP_ASM_INCLUDE    ?= kern/arm/tramp-mp-asm-default.h
CPPFLAGS                += -DTRAMP_MP_ASM_INCLUDE=\"$(srcdir)/$(TRAMP_MP_ASM_INCLUDE)\"

ifeq ("$(filter LIBUART, $(SUBSYSTEMS))","LIBUART")
  LIBUART			:= uart/libuart.a
endif

CONFIG_KERNEL_LOAD_ADDR := $(RAM_PHYS_BASE)

ifneq ($(CONFIG_MP),)
ifneq ($(CONFIG_ARM_MPCORE)$(CONFIG_ARM_CORTEX_A9)$(CONFIG_ARM_CORTEX_A5),)
ifeq ($(MPCORE_PHYS_BASE),)
$(error $(MODULES_FILE_BSP) needs to set MPCORE_PHYS_BASE variable)
endif
endif
endif

MODULES_FILES += $(MODULES_FILE) $(MODULES_FILE_BSP)
